import winston from 'winston'
import path from 'path'

// Define log levels and colors
const levels = {
  error: 0,
  warn: 1,
  info: 2,
  http: 3,
  debug: 4,
}

const colors = {
  error: 'red',
  warn: 'yellow',
  info: 'green',
  http: 'magenta',
  debug: 'white',
}

// Tell winston that you want to link the colors
winston.addColors(colors)

// Define format for console output
const consoleFormat = winston.format.combine(
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }),
  winston.format.colorize({ all: true }),
  winston.format.printf(
    (info) => `${info.timestamp} ${info.level}: ${info.message}${
      info.stack ? '\n' + info.stack : ''
    }${
      info.error && info.error !== info.message ? '\n' + JSON.stringify(info, null, 2) : ''
    }`
  )
)

// Define format for file output
const fileFormat = winston.format.combine(
  winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss:ms' }),
  winston.format.errors({ stack: true }),
  winston.format.json()
)

// Define transports
const transports = [
  // Console transport for development
  new winston.transports.Console({
    format: consoleFormat,
    level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug'
  }),
  
  // File transport for errors
  new winston.transports.File({
    filename: path.join(process.cwd(), 'logs', 'error.log'),
    level: 'error',
    format: fileFormat,
    maxsize: 5242880, // 5MB
    maxFiles: 5,
  }),
  
  // File transport for all logs
  new winston.transports.File({
    filename: path.join(process.cwd(), 'logs', 'combined.log'),
    format: fileFormat,
    maxsize: 5242880, // 5MB
    maxFiles: 5,
  })
]

// Create logger instance
export const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  levels,
  format: fileFormat,
  transports,
  exitOnError: false,
})

// Create logs directory if it doesn't exist
import fs from 'fs'
const logDir = path.join(process.cwd(), 'logs')
if (!fs.existsSync(logDir)) {
  fs.mkdirSync(logDir, { recursive: true })
}

// Handle uncaught exceptions and unhandled rejections
logger.exceptions.handle(
  new winston.transports.File({ 
    filename: path.join(logDir, 'exceptions.log'),
    format: fileFormat
  })
)

process.on('unhandledRejection', (reason, promise) => {
  logger.error('Unhandled Rejection at Promise', { 
    promise, 
    reason: reason instanceof Error ? reason.message : reason 
  })
})

// Export logger with additional utility methods
export default {
  ...logger,
  
  // Request logging utility
  logRequest: (req: any, res: any, responseTime?: number) => {
    const logData = {
      method: req.method,
      url: req.originalUrl,
      status: res.statusCode,
      ip: req.ip,
      userAgent: req.get('User-Agent'),
      userId: req.user?.id,
      responseTime: responseTime ? `${responseTime}ms` : undefined
    }
    
    if (res.statusCode >= 400) {
      logger.error('HTTP Error Response', logData)
    } else {
      logger.info('HTTP Request', logData)
    }
  },

  // Authentication logging
  logAuth: (event: string, userId?: string, details?: any) => {
    logger.info('Auth Event', {
      event,
      userId,
      timestamp: new Date().toISOString(),
      ...details
    })
  },

  // Security logging
  logSecurity: (event: string, details: any) => {
    logger.warn('Security Event', {
      event,
      timestamp: new Date().toISOString(),
      ...details
    })
  },

  // Performance logging
  logPerformance: (operation: string, duration: number, details?: any) => {
    const level = duration > 1000 ? 'warn' : 'info'
    logger.log(level, 'Performance', {
      operation,
      duration: `${duration}ms`,
      timestamp: new Date().toISOString(),
      ...details
    })
  }
}